import { useEffect, useMemo, useRef, useState } from "react";
import { WebsocketProvider } from "y-websocket";
import { IndexeddbPersistence } from "y-indexeddb";
import * as Y from "yjs";

// 创建Yjs协同文档实例
const ydoc = new Y.Doc();

const provider = new WebsocketProvider(
  "ws://localhost:1234",
  "yjs-demo-room",
  ydoc
);

// 生成随机颜色
function getRandomColor() {
  return `#${Math.floor(Math.random() * 0xffffff)
    .toString(16)
    .padStart(6, "0")}`;
}

// 生成随机用户名
function getRandomName() {
  return `user-${Math.random().toString(36).slice(2, 8)}`;
}
// 本地用户初始化信息
const username = getRandomName();
const userColor = getRandomColor();

provider.awareness.setLocalStateField("user", {
  name: username,
  color: userColor,
});

// 防抖函数
function debounce<T extends (...args: any[]) => void>(fn: T, delay: number) {
  let timer: NodeJS.Timeout;
  return function (this: any, ...args: Parameters<T>) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  } as T;
}

function App() {
  const [text, setText] = useState("");
  const [currentUser, setCurrentUser] = useState({ name: "", color: "" });
  const [remoteUsers, setRemoteUsers] = useState<Map<number, any>>(new Map());
  const [remoteCursors, setRemoteCursors] = useState<Map<number, any>>(
    new Map()
  );

  // 引用共享文本对象
  const yTextRef = useRef<Y.Text | null>(null);
  // 本地存储引用
  const persistenceRef = useRef<IndexeddbPersistence | null>(null);

  // 初始化协同环境
  useEffect(() => {
    const yText = ydoc.getText("shared-text");
    yTextRef.current = yText;

    // 初始化本地存储
    const persistence = new IndexeddbPersistence("yjs-input-db", ydoc);
    persistenceRef.current = persistence;

    // 设置本地用户状态
    setCurrentUser(
      provider.awareness.getLocalState()?.user ?? { name: "", color: "" }
    );

    // 监听远程用户状态
    const awarenessChangeHandler = () => {
      const states = provider.awareness.getStates();
      const users = new Map<number, any>();
      const cursors = new Map<number, any>();

      for (const [clientID, state] of states) {
        if (clientID === provider.awareness.clientID) continue; // 跳过本地用户
        users.set(clientID, state.user);
        cursors.set(clientID, state.cursor);
      }

      setRemoteUsers(users);
      setRemoteCursors(cursors);
    };
    provider.awareness.on("change", awarenessChangeHandler);

    // 从indexedDB同步本地内容
    persistence.whenSynced.then(() => {
      setText(yText.toString());
    });

    const updateHandler = () => {
      setText(yText.toString());
    };

    ydoc.on("update", updateHandler);

    // 清理副作用
    return () => {
      provider.awareness.off("change", awarenessChangeHandler);
      ydoc.off("update", updateHandler);
    };
  }, []);

  // 实时光标位置同步
  useEffect(() => {
    const handleMouseMove = (event: MouseEvent) => {
      provider.awareness.setLocalStateField("cursor", {
        x: event.clientX,
        y: event.clientY,
        windowSize: {
          width: window.innerWidth,
          height: window.innerHeight,
        },
      });
    };
    document.addEventListener("mousemove", handleMouseMove);

    return () => {
      document.removeEventListener("mousemove", handleMouseMove);
    };
  }, []);

  const debounceHandleChange = useMemo(() => {
    return debounce((value: string) => {
      if (yTextRef.current) {
        yTextRef.current.delete(0, yTextRef.current.length);
        yTextRef.current.insert(0, value);
      }
    }, 100);
  }, []);

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    const value = event.target.value;
    setText(value);
    // 防抖的协同文本输入处理
    debounceHandleChange(value);
  };

  // 鼠标映射到当前窗口的位置处理
  const getCursorPosition = (cursor: any) => {
    if (!cursor || !cursor.windowSize) return null;
    const { x, y, windowSize } = cursor;
    return {
      cursorX: (x / windowSize.width) * window.innerWidth,
      cursorY: (y / windowSize.height) * window.innerHeight,
    };
  };

  return (
    <>
      <h3>
        当前用户
        <span style={{ color: currentUser.color, fontWeight: "bold" }}>
          {currentUser.name}
        </span>
      </h3>
      {/* 其他在线用户 */}
      <div style={{ margin: "1em 0" }}>
        <span>其他在线用户</span>
        {Array.from(remoteUsers).map(([clientId, user]) => (
          <div key={clientId}>
            <span style={{ color: user.color, fontWeight: "bold" }}>
              {user.name}
            </span>
          </div>
        ))}
      </div>

      <textarea
        rows={10}
        value={text}
        onChange={handleChange}
        style={{
          width: "100%",
          height: "300px",
          fontSize: "16px",
          padding: "8px",
          border: "1px solid #ccc",
          borderRadius: "4px",
          boxSizing: "border-box",
        }}
      />

      {/* 渲染其他用户光标的移动效果 */}
      {Array.from(remoteCursors).map(([clientId, cursor]) => {
        const position = getCursorPosition(cursor);
        const user = remoteUsers.get(clientId);
        if (!position || !user) return null;
        return (
          <div
            key={clientId}
            style={{
              position: "absolute",
              left: position.cursorX,
              top: position.cursorY,
              transform: "translate(-50%, -100%)",
              zIndex: 1000,
              pointerEvents: "none",
              textAlign: "center",
            }}
          >
            <div
              style={{
                backgroundColor: user.color,
                color: "fff",
                padding: "2px 6px",
                borderRadius: "4px",
                fontWeight: "bold",
                marginBottom: "4px",
                whiteSpace: "nowrap",
              }}
            >
              {user.name}
            </div>
            <div
              style={{
                width: "10px",
                height: "10px",
                backgroundColor: user.color,
                borderRadius: "50%",
                border: "2px solid white",
              }}
            />
          </div>
        );
      })}
    </>
  );
}

export default App;
